﻿namespace EFRepositoryTests
{
  using System;
  using System.Configuration;
  using System.Linq;
  using System.Transactions;
  using Builder;
  using Entities;
  using FluentAssertions;
  using NUnit.Framework;
  using UnityRepository.Repositories;

  [Category("Integration")]
  [TestFixture]
  public class AppManCoEmailRepositoryTests
  {
      [SetUp]
      public void Setup()
      {
        String connectionString = ConfigurationManager.ConnectionStrings["Unity"].ConnectionString;

        this._transactionScope = new TransactionScope();
        this._appManCoEmailRepository = new AppManCoEmailRepository(connectionString);
        this._manCoRepository = new ManCoRepository(connectionString);
        this._applicationRepository = new ApplicationRepository(connectionString);
        this._docTypeRepository = new DocTypeRepository(connectionString);
        this._manCo1 = BuildMeA.ManCo("description", "code");
        this._manCo2 = BuildMeA.ManCo("description2", "code2");
        this._application1 = BuildMeA.Application("code", "description");
        this._application2 = BuildMeA.Application("code2", "description2");
        this._docType1 = BuildMeA.DocType("code", "description");

        this._manCoRepository.Create(this._manCo1);
        this._manCoRepository.Create(this._manCo2);
        this._applicationRepository.Create(this._application1);
        this._applicationRepository.Create(this._application2);
        this._docTypeRepository.Create(this._docType1);

        this._appManCoEmail = BuildMeA.AppManCoEmail(this._application1.Id, this._manCo1.Id, this._docType1.Id, "accountNumber", "email");
        this._appManCoEmail2 = BuildMeA.AppManCoEmail(this._application1.Id, this._manCo2.Id, this._docType1.Id, "accountNumber2", "email2");
        this._appManCoEmail3 = BuildMeA.AppManCoEmail(this._application1.Id, this._manCo1.Id, this._docType1.Id, "accountNumber3", "email3");
        this._appManCoEmail4 = BuildMeA.AppManCoEmail(this._application1.Id, this._manCo2.Id, this._docType1.Id, "accountNumber4", "email4");  
      }

      [TearDown]
      public void TearDown()
      {
        this._transactionScope.Dispose();
      }

      private TransactionScope _transactionScope;
      private AppManCoEmailRepository _appManCoEmailRepository;
      private ManCoRepository _manCoRepository;
      private ApplicationRepository _applicationRepository;
      private DocTypeRepository _docTypeRepository;
      private AppManCoEmail _appManCoEmail;
      private AppManCoEmail _appManCoEmail2;
      private AppManCoEmail _appManCoEmail3;
      private AppManCoEmail _appManCoEmail4;
      private ManCo _manCo1;
      private ManCo _manCo2;
      private Application _application1;
      private Application _application2;
      private DocType _docType1;

      [Test]
      public void GivenAnApplicationManCoEmail_WhenITryToSaveToTheDatabase_ItIsSavedToTheDatabase()
      {
        int initialCount = _appManCoEmailRepository.Entities.Count();
        _appManCoEmailRepository.Create(_appManCoEmail);

        _appManCoEmailRepository.Entities.Count().Should().Be(initialCount + 1);
      }

      [Test]
      public void GivenAnAppManCoEmail_WhenITryToSearchForItById_ItIsRetrievedFromTheDatabase()
      {
        _appManCoEmailRepository.Create(_appManCoEmail);

        var result = _appManCoEmailRepository.GetAppManCoEmail(_appManCoEmail.Id);

        result.Should().NotBeNull();
        result.Id.ShouldBeEquivalentTo(_appManCoEmail.Id);
      }

      [Test]
      public void GivenAnAppIdAndManCoId_WhenITryToSearchByAppIdAndManCoId_AppManCoEmailsAreRetrievedFromTheDB()
      {
          _appManCoEmailRepository.Create(_appManCoEmail);
          _appManCoEmailRepository.Create(_appManCoEmail2);
          _appManCoEmailRepository.Create(_appManCoEmail3);
          _appManCoEmailRepository.Create(_appManCoEmail4);

          var result = _appManCoEmailRepository.GetAppManCoEmails(_appManCoEmail2.ApplicationId,_appManCoEmail2.ManCoId);

          result.Should().NotBeNull();
          result.Count.ShouldBeEquivalentTo(2);
      }

      [Test]
      public void GivenANullAppIdAndManCoId_WhenITryToSearchByNullAppIdAndManCoId_AppManCoEmailsAreRetrievedFromTheDB()
      {
          _appManCoEmailRepository.Create(_appManCoEmail);
          _appManCoEmailRepository.Create(_appManCoEmail2);
          _appManCoEmailRepository.Create(_appManCoEmail3);
          _appManCoEmailRepository.Create(_appManCoEmail4);

          var result = _appManCoEmailRepository.GetAppManCoEmails(null, _appManCoEmail2.ManCoId);

          result.Should().NotBeNull();
          result.Count.ShouldBeEquivalentTo(2);
      }

      [Test]
      public void GivenAnAppIdWithZerovalueAndManCoId_WhenITryToSearchByNullAppIdAndManCoId_AppManCoEmailsAreRetrievedFromTheDB()
      {
          _appManCoEmailRepository.Create(_appManCoEmail);
          _appManCoEmailRepository.Create(_appManCoEmail2);
          _appManCoEmailRepository.Create(_appManCoEmail3);
          _appManCoEmailRepository.Create(_appManCoEmail4);

          var result = _appManCoEmailRepository.GetAppManCoEmails(0, _appManCoEmail2.ManCoId);

          result.Should().NotBeNull();
          result.Count.ShouldBeEquivalentTo(2);
      }


      [Test]
      public void GivenAnAppManCoEmail_WhenITryToUpdateIt_TheAppManCoEmailIsUpdated()
      {
        _appManCoEmailRepository.Create(_appManCoEmail);

        var result = _appManCoEmailRepository.GetAppManCoEmail(_appManCoEmail.Id);

        var retrievedAccountNumber = result.AccountNumber;
        var retrievedEmail = result.Email;
 
        this._appManCoEmailRepository.UpdateAppManCoEmail(_appManCoEmail.Id, _appManCoEmail.ApplicationId, _appManCoEmail.ManCoId, _appManCoEmail.DocTypeId, "account number updated","jean@northtrust.com", "userName");

        var result2 = _appManCoEmailRepository.GetAppManCoEmail(_appManCoEmail.Id);

        result.Should().NotBeNull();
        result2.Should().NotBeNull();
        result.Id.ShouldBeEquivalentTo(result2.Id);
        result.ManCoId.ShouldBeEquivalentTo(result2.ManCoId);
        result2.AccountNumber.Should().NotBe(retrievedAccountNumber);
        result2.Email.Should().NotBe(retrievedEmail);
      }

      [Test]
      public void WhenIDeleteAnAppManCoEmail_ThenItIsDeleted()
      {
        _appManCoEmailRepository.Create(_appManCoEmail);

        AppManCoEmail retrievedAppManCoEmail = _appManCoEmailRepository.GetAppManCoEmail(_appManCoEmail.Id);
        _appManCoEmailRepository.Delete(retrievedAppManCoEmail);
        AppManCoEmail deletedAppManCoEmail = _appManCoEmailRepository.GetAppManCoEmail(retrievedAppManCoEmail.Id);
        deletedAppManCoEmail.Should().BeNull();
      }

    [Test]
    public void GivenNoSearchCriteria_WhenISearchForAppManCoEmails_TheyAreReturned()
    {
      const Int32 PageNumber = 1;
      const Int32 NumberOfItems = 10;

      this._appManCoEmailRepository.Create(this._appManCoEmail);
      this._appManCoEmailRepository.Create(this._appManCoEmail2);
      this._appManCoEmailRepository.Create(this._appManCoEmail3);
      this._appManCoEmailRepository.Create(this._appManCoEmail4);

      PagedResult<AppManCoEmail> results = this._appManCoEmailRepository.GetPagedAppManCoEmails(null, null, null, PageNumber, NumberOfItems);

      results.TotalItems.Should().BeGreaterOrEqualTo(4);
      results.Results.Count.Should().BeGreaterOrEqualTo(4);
    }

    [Test]
    public void GivenAnAccountNumber_WhenISearchForAppManCoEmails_OnlyEmailsForThatAccountNumberAreReturned()
    {
      const Int32 PageNumber = 1;
      const Int32 NumberOfItems = 10;

      this._appManCoEmailRepository.Create(this._appManCoEmail);
      this._appManCoEmailRepository.Create(this._appManCoEmail2);

      PagedResult<AppManCoEmail> results = this._appManCoEmailRepository.GetPagedAppManCoEmails("accountNumber2", null, null, PageNumber, NumberOfItems);

      results.TotalItems.Should().Be(1);
      results.Results[0].AccountNumber.Should().Be("accountNumber2");
    }

    [Test]
    public void GivenAnApplicationId__WhenISearchForAppManCoEmails_OnlyEmailsForThatApplicationAreReturned()
    {
      const Int32 PageNumber = 1;
      const Int32 NumberOfItems = 10;

      AppManCoEmail appManCoEmailOfDifferentApplication = BuildMeA.AppManCoEmail(this._application2.Id, this._manCo2.Id, this._docType1.Id, "accountNumber4", "email4");

      this._appManCoEmailRepository.Create(this._appManCoEmail);
      this._appManCoEmailRepository.Create(this._appManCoEmail2);
      this._appManCoEmailRepository.Create(appManCoEmailOfDifferentApplication);

      PagedResult<AppManCoEmail> results = this._appManCoEmailRepository.GetPagedAppManCoEmails(null, this._application1.Id, null, PageNumber, NumberOfItems);

      results.TotalItems.Should().Be(2);
      results.Results.Count(a => a.Application.Code == this._application1.Code).Should().Be(2);
    }

    [Test]
    public void GivenAManCoId__WhenISearchForAppManCoEmails_OnlyEmailsForThaManCoAreReturned()
    {
      const Int32 PageNumber = 1;
      const Int32 NumberOfItems = 10;

      this._appManCoEmailRepository.Create(this._appManCoEmail);
      this._appManCoEmailRepository.Create(this._appManCoEmail2);

      PagedResult<AppManCoEmail> results = this._appManCoEmailRepository.GetPagedAppManCoEmails(null, null, this._manCo1.Id, PageNumber, NumberOfItems);

      results.TotalItems.Should().Be(1);
      results.Results.Count(a => a.ManCo.Code == this._manCo1.Code).Should().Be(1);
    }
  }
}
